import os
import time
import platform
import re
from pathlib import Path
import argparse
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import git  # 需要安装 gitpython 库
from openai import OpenAI
from promptConst import const
from configuration import Config
from utils.gpt import GPTClient

from CodeAnalyzer  import CodeAnalyzer

import logging

class GitChangeHandler:
    """
    Git 变更处理器类。
    用于分析 Git 仓库的变更并生成提交信息。
    """

    def __init__(self, repo_path: str, config: Config):
        """
        初始化 Git 变更处理器。

        :param repo_path: Git 仓库路径。
        :param config: 配置对象。
        """
        self.repo_path = repo_path
        self.config = config
        
        # 添加日志记录器
        self.logger = logging.getLogger(__name__)
        
        try:
            self.client = OpenAI(
                api_key=self.config.api_key,
                base_url=self.config.base_url,
                timeout=30.0  # 设置超时时间
            )
            # 测试连接
            response = self.client.chat.completions.create(
                model=self.config.model,
                messages=[{"role": "user", "content": "test"}],
                max_tokens=5
            )
            self.logger.info("API连接测试成功")
        except Exception as e:
            self.logger.error(f"API初始化失败: {str(e)}")
            self.logger.error(f"base_url: {self.config.base_url}")
            raise

        self.committer = self.config.committer
        self.const = const()
        self.repo = git.Repo(repo_path)  # 初始化 Git 仓库对象
        self.gpt_client = GPTClient(config=self.config)
        self.logger=logging

    # def call_gpt(self, prompt: str) -> str:
    #     """
    #     使用 OpenAI API 调用 GPT 模型生成文本。
    #
    #     :param prompt: 输入的提示文本。
    #     :return: GPT 生成的文本。
    #     """
    #     try:
    #         response = self.client.chat.completions.create(
    #             model=self.config.model,  # 模型名称（例如 deepseek-chat）
    #             messages=[
    #                 {"role": "system", "content": "你是一个 AI 助手，帮助用户生成 Git 提交信息。"},
    #                 {"role": "user", "content": prompt},
    #             ],
    #             stream=False
    #         )
    #         return response.choices[0].message.content
    #     except Exception as e:
    #         print(f"调用 GPT 失败: {e}")
    #         return "调用GPT失败，请检查是否开启代理或者配置是否正确"

    def get_git_diff(self) -> str:
        """
        获取 Git 仓库的变更差异。

        :return: 变更差异字符串。
        """
        # 获取未暂存的变更
        diff = self.repo.git.diff()
        if not diff:
            # 获取已暂存的变更
            diff = self.repo.git.diff("--cached")
        return diff

    def analyze_changes_with_ai(self, diff: str, version: str, project_summary: str) -> str:
        """
        调用 AI 大模型分析 Git 变更并生成提交信息。

        :param diff: Git 变更差异字符串。
        :param version: 版本号。
        :param project_summary: 项目概览。
        :return: 生成的提交信息。
        """
        try:
            # 打印所有的参数
            self.logger.info(f"当前版本: {version}")
            self.logger.info(f"项目概览: {project_summary}")
            
            commit_format = self.config.commit_format
            commit_standard = self.config.commit_standard
            # 设置默认的最大长度
            max_length = 4000
            if hasattr(self.config, 'max_length'):
                try:
                    max_length = int(self.config.max_length)
                except (ValueError, TypeError):
                    self.logger.warning(f"max_length 配置无效，使用默认值: {max_length}")

            # 确保 diff 不为空
            if not diff:
                return "没有检测到代码变更"

            # 分段处理长文本
            diff_length = len(diff)
            segments = []
            for i in range(0, diff_length, max_length):
                segments.append(diff[i:i + max_length])

            results = []
            for segment in segments:
                try:
                    prompt = self.const.promt1(
                        version=version, 
                        diff=segment, 
                        committer=self.committer,
                        commit_format=commit_format, 
                        commit_standard=commit_standard, 
                        project_summary=project_summary
                    )
                    result = self.gpt_client.call_gpt(prompt=prompt)
                    if result:
                        results.append(result)
                except Exception as e:
                    self.logger.error(f"处理代码段时出错: {str(e)}")

            if not results:
                return "生成提交信息失败"

            # 合并结果并生成最终提交信息
            all_results = "".join(results)
            final_prompt = self.const.promt2(
                version=version,
                all_results=all_results,
                committer=self.committer,
                commit_format=commit_format,
                commit_standard=commit_standard,
                project_summary=project_summary
            )
            final_result = self.gpt_client.call_gpt(prompt=final_prompt)
            return final_result if final_result else "生成提交信息失败"
        except Exception as e:
            self.logger.error(f"分析变更时出错: {str(e)}")
            return f"生成提交信息失败: {str(e)}"


    def get_latest_version(self) -> str:
        """
        获取最新的版本号。

        :return: 最新的版本号字符串。
        """
        try:
            # 获取最新的提交信息
            latest_commit = self.repo.head.commit.message
            version = self.gpt_client.call_gpt(prompt=f'''
#任务
从已知中提取返回版本号
#严格遵守的原则
- 如果找不到版本号，直接返回默认版本号：1.0.0
- 返回的数据格式只能是1.0.0这种类似的版本号格式
#已知
{latest_commit}
#返回示例
1.0.0
            ''')
            return version
        except Exception as e:
            print(f"获取最新版本号失败: {e}")
            return "1.0.0"  # 默认版本号

    def extract_version(self,text):
        # 定义一个正则表达式模式来匹配版本号
        pattern = r'\bv?(\d+\.\d+\.\d+)\b'

        # 使用re.search()查找第一个匹配的版本号
        match = re.search(pattern, text)

        if match:
            return match.group(1)  # 返回匹配的版本号部分
        else:
            return None  # 如果没有找到匹配项，返回None

    def get_next_version(self) -> str:
        """
        获取下一个版本号。

        :return: 下一个版本号字符串。
        """
        try:
            current_version = self.get_latest_version()
            current_version = self.extract_version(current_version)
            if current_version is None:
                self.logger.warning("获取最新版本号失败，使用默认版本号 1.0.0")
                return "1.0.0"
                
            # 清理版本号字符串，确保只包含数字和点
            current_version = current_version.strip()
            if not re.match(r'^\d+\.\d+\.\d+$', current_version):
                self.logger.warning(f"版本号格式不正确: {current_version}，使用默认版本号 1.0.0")
                return "1.0.0"
                
            major, minor, patch = map(int, current_version.split("."))
            patch += 1  # 修订号加 1
            return f"{major}.{minor}.{patch}"
        except Exception as e:
            self.logger.error(f"生成下一个版本号时出错: {str(e)}")
            return "1.0.0"

    def generate_commit_message(self) -> str:
        """
        单次执行：生成 Git 变更的提交信息。

        :return: 生成的提交信息。
        """
        # 获取 Git 仓库的变更
        diff = self.get_git_diff()
        print(diff)
        summary='无项目概览信息'
        if not diff:
            print("没有检测到 Git 变更。")
            return "没有检测到 Git 变更。"

        print(f"Git 变更:\n{diff}")
        if self.config.enhanced_mode:
            self.logger.info("增强模式已开启")
            # TODO:开始分析项目文件
            code_analyzer = CodeAnalyzer(
                language_name='python',
                language_repo_url="https://github.com/tree-sitter/tree-sitter-python",
                config=self.config
            )
            # 获取到项目summary
            summary = code_analyzer.analyze_project(self.repo_path, detail=False)

        # 调用 AI 分析变更并生成提交信息
        try:
            version = self.get_next_version()
            self.logger.info(f"当前版本: {version}")
            commit_message = self.analyze_changes_with_ai(diff, str(version),project_summary=summary)
            self.logger.info(f"生成的提交信息: {commit_message}")
            #commit_message_with_version = f"{commit_message}"

            # 将版本信息更新到配置文件中
            if version is not None:
                self.config.update({"current_version": version})

            print(f"生成的提交信息: {commit_message}")
            return commit_message
        except Exception as e:
            print(f"生成提交信息失败: {e}")
            return f"生成提交信息失败: {e}"


class GitChangeMonitor(FileSystemEventHandler):
    """
    Git 变更监控类，继承自 watchdog.events.FileSystemEventHandler。
    用于监控文件系统中的文件修改事件，并分析 Git 变更。
    """

    def __init__(self, repo_path: str, config: Config):
        """
        初始化 Git 变更监控器。

        :param repo_path: Git 仓库路径。
        :param config: 配置对象。
        """
        self.repo_path = repo_path
        self.handler = GitChangeHandler(repo_path, config)

    def on_modified(self, event):
        """
        处理文件修改事件。

        :param event: 文件系统事件对象，包含事件类型和路径等信息。
        """
        if event.is_directory:
            return  # 忽略目录修改事件

        file_path = event.src_path
        print(f"检测到文件修改: {file_path}")

        # 调用 GitChangeHandler 生成提交信息
        self.handler.generate_commit_message()


def monitor_git_repo(repo_path: str, config: Config):
    """
    监控指定 Git 仓库的文件变化。

    :param repo_path: Git 仓库路径。
    :param config: 配置对象。
    """
    if not os.path.exists(repo_path):
        print(f"目录不存在: {repo_path}")
        return

    # 创建事件处理器和观察者
    event_handler = GitChangeMonitor(repo_path, config)
    observer = Observer()
    observer.schedule(event_handler, repo_path, recursive=True)
    observer.start()
    print(f"已启动 Git 仓库监控: {repo_path}")

    try:
        while True:
            time.sleep(1)  # 主线程休眠，避免占用 CPU
    except KeyboardInterrupt:
        observer.stop()  # 捕获 Ctrl+C 信号，停止监控
    observer.join()
    print("Git 仓库监控已停止")


def get_default_git_repo_directory() -> str:
    """
    获取默认的 Git 仓库目录（跨平台支持）。

    :return: 默认 Git 仓库目录路径。
    """
    system = platform.system()
    if system == "Windows":
        return "D:/code"  # Windows 默认监控 D:/code
    elif system in ("Linux", "Darwin"):  # Darwin 是 macOS
        return os.path.expanduser("~/code")  # Linux/macOS 默认监控 ~/code
    else:
        raise NotImplementedError(f"不支持的操作系统: {system}")


def main():
    """
    主函数，解析命令行参数并执行相应操作。
    """
    config = Config()
    parser = argparse.ArgumentParser(description="Git 变更分析与提交信息生成工具")
    parser.add_argument(
        "--mode",
        choices=["monitor", "single"],
        default="single",
        help="运行模式：monitor（监控模式）或 single（单次执行模式）",
    )
    parser.add_argument(
        "--repo",
        default=get_default_git_repo_directory(),
        help="Git 仓库路径（默认为系统默认路径）",
    )
    args = parser.parse_args()

    # 如果目录不存在，则创建
    if not os.path.exists(args.repo):
        print(f"Git 仓库目录不存在，正在创建: {args.repo}")
        os.makedirs(args.repo)

    # 初始化 Git 仓库（如果目录不是 Git 仓库）
    if not os.path.exists(os.path.join(args.repo, ".git")):
        print(f"初始化 Git 仓库: {args.repo}")
        git.Repo.init(args.repo)

    # 根据模式执行相应操作
    if args.mode == "monitor":
        monitor_git_repo(args.repo, config)
    else:
        handler = GitChangeHandler(args.repo, config)
        handler.generate_commit_message()


    def analyze_modular_design(project_path):
        """
        分析项目的模块化设计。
        识别项目中的功能模块、组件和服务，并生成详细的分析报告。

        :param project_path: 项目路径
        """
        print(f"分析模块化设计: {project_path}")

        # 定义模块类型
        module_types = {
            "功能模块": ["module", "feature", "service"],
            "组件": ["component", "widget", "ui"],
            "服务": ["api", "endpoint", "microservice"]
        }

        # 遍历项目目录
        for root, dirs, files in os.walk(project_path):
            print(f"\n目录: {root}")

            # 分析每个文件
            for file in files:
                file_path = Path(root) / file
                print(f"分析文件: {file_path}")

                # 检查文件是否包含模块
                if file_path:
                    print(f"模块: {file_path}")

                # 识别模块类型
                for module_type, keywords in module_types.items():
                    for keyword in keywords:
                        if keyword in file.lower():
                            print(f"识别为 {module_type}: {file_path}")

        # 生成模块化设计报告
        generate_modular_report(project_path)

    def generate_modular_report(project_path):
        """
        生成模块化设计报告。

        :param project_path: 项目路径
        """
        print(f"\n生成模块化设计报告: {project_path}")
        report_path = Path(project_path) / "modular_design_report.txt"
        with open(report_path, "w", encoding="utf-8") as report_file:
            report_file.write("模块化设计分析报告\n")
            report_file.write("=" * 30 + "\n")
            report_file.write(f"项目路径: {project_path}\n")
            report_file.write("识别模块类型:\n")
            report_file.write("- 功能模块\n")
            report_file.write("- 组件\n")
            report_file.write("- 服务\n")
        print(f"报告已生成: {report_path}")



if __name__ == "__main__":
    main()